/**
 *  BlueCove - Java library for Bluetooth
 *
 *  Java docs licensed under the Apache License, Version 2.0
 *  http://www.apache.org/licenses/LICENSE-2.0
 *   (c) Copyright 2001, 2002 Motorola, Inc.  ALL RIGHTS RESERVED.
 *
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 *
 *  @version $Id: DataElement.java 2922 2009-03-14 20:50:11Z skarzhevskyy $
 */
package javax.bluetooth;

import java.util.Enumeration;
import java.util.Vector;

import com.intel.bluetooth.Utils;

/**
 * The <code>DataElement</code> class defines the various data types that a
 * Bluetooth service attribute value may have.
 *
 * The following table describes the data types and valid values that a
 * <code>DataElement</code> object can store.
 *
 * <TABLE BORDER>
 * <TR>
 * <TH>Data Type</TH>
 * <TH>Valid Values</TH>
 * </TR>
 * <TR>
 * <TD><code>NULL</code></TD>
 * <TD>represents a <code>null</code> value </TD>
 * </TR>
 * <TR>
 * <TD><code>U_INT_1</code></TD>
 * <TD><code>
 * long </code> value range [0, 255]</TD>
 * </TR>
 * <TR>
 * <TD><code>U_INT_2</code></TD>
 * <TD><code>long</code> value range [0, 2<sup>16</sup>-1]</TD>
 * </TR>
 * <TR>
 * <TD><code>U_INT_4</code></TD>
 * <TD><code>long</code> value range [0, 2<sup>32</sup>-1]</TD>
 * </TR>
 * <TR>
 * <TD><code>U_INT_8</code></TD>
 * <TD><code>byte[]</code> value range [0, 2<sup>64</sup>-1]</TD>
 * </TR>
 * <TR>
 * <TD><code>U_INT_16</code></TD>
 * <TD><code>byte[]</code> value range [0, 2<sup>128</sup>-1]</TD>
 * </TR>
 * <TR>
 * <TD><code>INT_1</code></TD>
 * <TD><code>long</code> value range [-128, 127]</TD>
 * </TR>
 * <TR>
 * <TD><code>INT_2</code></TD>
 * <TD><code>long</code> value range [-2<sup>15</sup>, 2<sup>15</sup>-1]</TD>
 * </TR>
 * <TR>
 * <TD><code>INT_4</code></TD>
 * <TD><code>long</code> value range [-2<sup>31</sup>, 2<sup>31</sup>-1]</TD>
 * </TR>
 * <TR>
 * <TD><code>INT_8</code></TD>
 * <TD><code>long</code> value range [-2<sup>63</sup>, 2<sup>63</sup>-1]</TD>
 * </TR>
 * <TR>
 * <TD><code>INT_16</code></TD>
 * <TD><code>byte[]</code> value range [-2<sup>127</sup>, 2<sup>127</sup>-1]</TD>
 * </TR>
 * <TR>
 * <TD><code>URL</code></TD>
 * <TD><code>java.lang.String</code></TD>
 * </TR>
 * <TR>
 * <TD><code>UUID</code></TD>
 * <TD><code>javax.bluetooth.UUID</code></TD>
 * </TR>
 * <TR>
 * <TD><code>BOOL</code></TD>
 * <TD><code>boolean</code></TD>
 * </TR>
 * <TR>
 * <TD><code>STRING</code></TD>
 * <TD><code>java.lang.String</code></TD>
 * </TR>
 * <TR>
 * <TD><code>DATSEQ</code></TD>
 * <TD><code>java.util.Enumeration</code></TD>
 * </TR>
 * <TR>
 * <TD><code>DATALT</code></TD>
 * <TD><code>java.util.Enumeration</code></TD>
 * </TR>
 * </TABLE>
 *
 *
 */

public class DataElement {

	/*
	 * The following section defines public, static and instance member
	 * variables used in the implementation of the methods.
	 */

	/**
	 * Defines data of type NULL.
	 *
	 * The value for data type <code>DataElement.NULL</code> is implicit,
	 * i.e., there is no representation of it. Accordingly there is no method to
	 * retrieve it, and attempts to retrieve the value will throw an exception.
	 * <P>
	 * The value of <code>NULL</code> is 0x00 (0).
	 *
	 */
	public static final int NULL = 0x0000;

	/**
	 * Defines an unsigned integer of size one byte.
	 * <P>
	 * The value of the constant <code>U_INT_1</code> is 0x08 (8).
	 */
	public static final int U_INT_1 = 0x0008;

	/**
	 * Defines an unsigned integer of size two bytes.
	 * <P>
	 * The value of the constant <code>U_INT_2</code> is 0x09 (9).
	 */
	public static final int U_INT_2 = 0x0009;

	/**
	 * Defines an unsigned integer of size four bytes.
	 * <P>
	 * The value of the constant <code>U_INT_4</code> is 0x0A (10).
	 */
	public static final int U_INT_4 = 0x000A;

	/**
	 * Defines an unsigned integer of size eight bytes.
	 * <P>
	 * The value of the constant <code>U_INT_8</code> is 0x0B (11).
	 */
	public static final int U_INT_8 = 0x000B;

	/**
	 * Defines an unsigned integer of size sixteen bytes.
	 * <P>
	 * The value of the constant <code>U_INT_16</code> is 0x0C (12).
	 */
	public static final int U_INT_16 = 0x000C;

	/**
	 * Defines a signed integer of size one byte.
	 * <P>
	 * The value of the constant <code>INT_1</code> is 0x10 (16).
	 */
	public static final int INT_1 = 0x0010;

	/**
	 * Defines a signed integer of size two bytes.
	 * <P>
	 * The value of the constant <code>INT_2</code> is 0x11 (17).
	 */
	public static final int INT_2 = 0x0011;

	/**
	 * Defines a signed integer of size four bytes.
	 * <P>
	 * The value of the constant <code>INT_4</code> is 0x12 (18).
	 */
	public static final int INT_4 = 0x0012;

	/**
	 * Defines a signed integer of size eight bytes.
	 * <P>
	 * The value of the constant <code>INT_8</code> is 0x13 (19).
	 */
	public static final int INT_8 = 0x0013;

	/**
	 * Defines a signed integer of size sixteen bytes.
	 * <P>
	 * The value of the constant <code>INT_16</code> is 0x14 (20).
	 */
	public static final int INT_16 = 0x0014;

	/**
	 * Defines data of type URL.
	 * <P>
	 * The value of the constant <code>URL</code> is 0x40 (64).
	 */
	public static final int URL = 0x0040;

	/**
	 * Defines data of type UUID.
	 * <P>
	 * The value of the constant <code>UUID</code> is 0x18 (24).
	 */
	public static final int UUID = 0x0018;

	/**
	 * Defines data of type BOOL.
	 * <P>
	 * The value of the constant <code>BOOL</code> is 0x28 (40).
	 */
	public static final int BOOL = 0x0028;

	/**
	 * Defines data of type STRING.
	 * <P>
	 * The value of the constant <code>STRING</code> is 0x20 (32).
	 */
	public static final int STRING = 0x0020;

	/**
	 * Defines data of type DATSEQ. The service attribute value whose data has
	 * this type must consider all the elements of the list, i.e. the value is
	 * the whole set and not a subset. The elements of the set can be of any
	 * type defined in this class, including DATSEQ.
	 * <P>
	 * The value of the constant <code>DATSEQ</code> is 0x30 (48).
	 */
	public static final int DATSEQ = 0x0030;

	/**
	 * Defines data of type DATALT. The service attribute value whose data has
	 * this type must consider only one of the elements of the set, i.e., the
	 * value is the not the whole set but only one element of the set. The user
	 * is free to choose any one element. The elements of the set can be of any
	 * type defined in this class, including DATALT.
	 * <P>
	 * The value of the constant <code>DATALT</code> is 0x38 (56).
	 */
	public static final int DATALT = 0x0038;

	private Object value;

	private int valueType;

	/**
	 * Creates a <code>DataElement</code> of type <code>NULL</code>,
	 * <code>DATALT</code>, or <code>DATSEQ</code>.
	 *
	 * @see #NULL
	 * @see #DATALT
	 * @see #DATSEQ
	 *
	 * @param valueType
	 *            the type of DataElement to create: <code>NULL</code>,
	 *            <code>DATALT</code>, or <code>DATSEQ</code>
	 *
	 * @exception IllegalArgumentException
	 *                if <code>valueType</code> is not <code>NULL</code>,
	 *                <code>DATALT</code>, or <code>DATSEQ</code>
	 */

	public DataElement(int valueType) {
		switch (valueType) {
		case NULL:
			value = null;
			break;
		case DATALT:
		case DATSEQ:
			value = new Vector();
			break;
		default:
			throw new IllegalArgumentException("valueType " + typeToString(valueType)
					+ " is not DATSEQ, DATALT or NULL");
		}

		this.valueType = valueType;
	}

	/**
	 * Creates a <code>DataElement</code> whose data type is <code>BOOL</code>
	 * and whose value is equal to <code>bool</code>
	 *
	 * @see #BOOL
	 *
	 * @param bool
	 *            the value of the <code>DataElement</code> of type BOOL.
	 */

	public DataElement(boolean bool) {
		value = bool ? Boolean.TRUE : Boolean.FALSE;
		valueType = BOOL;
	}

	/**
	 * Creates a <code>DataElement</code> that encapsulates an integer value
	 * of size <code>U_INT_1</code>, <code>U_INT_2</code>,
	 * <code>U_INT_4</code>, <code>INT_1</code>, <code>INT_2</code>,
	 * <code>INT_4</code>, and <code>INT_8</code>. The legal values for
	 * the <code>valueType</code> and the corresponding attribute values are:
	 * <TABLE>
	 * <TR>
	 * <TH>Value Type</TH>
	 * <TH>Value Range</TH>
	 * </TR>
	 * <TR>
	 * <TD><code>U_INT_1</code></TD>
	 * <TD>[0, 2<sup>8</sup>-1]</TD>
	 * </TR>
	 * <TR>
	 * <TD><code>U_INT_2</code></TD>
	 * <TD>[0, 2<sup>16</sup>-1]</TD>
	 * </TR>
	 * <TR>
	 * <TD><code>U_INT_4</code></TD>
	 * <TD>[0, 2<sup>32</sup>-1]</TD>
	 * </TR>
	 * <TR>
	 * <TD><code>INT_1</code></TD>
	 * <TD>[-2<sup>7</sup>, 2<sup>7</sup>-1]</TD>
	 * </TR>
	 * <TR>
	 * <TD><code>INT_2</code></TD>
	 * <TD>[-2<sup>15</sup>, 2<sup>15</sup>-1]</TD>
	 * </TR>
	 * <TR>
	 * <TD><code>INT_4</code></TD>
	 * <TD>[-2<sup>31</sup>, 2<sup>31</sup>-1]</TD>
	 * </TR>
	 * <TR>
	 * <TD><code>INT_8</code></TD>
	 * <TD>[-2<sup>63</sup>, 2<sup>63</sup>-1]</TD>
	 * </TR>
	 * </TABLE> All other pairings are illegal and will cause an
	 * <code>IllegalArgumentException</code> to be thrown.
	 *
	 * @see #U_INT_1
	 * @see #U_INT_2
	 * @see #U_INT_4
	 * @see #INT_1
	 * @see #INT_2
	 * @see #INT_4
	 * @see #INT_8
	 *
	 * @param valueType
	 *            the data type of the object that is being created; must be one
	 *            of the following: <code>U_INT_1</code>,
	 *            <code>U_INT_2</code>, <code>U_INT_4</code>,
	 *            <code>INT_1</code>, <code>INT_2</code>,
	 *            <code>INT_4</code>, or <code>INT_8</code>
	 *
	 * @param value
	 *            the value of the object being created; must be in the range
	 *            specified for the given <code>valueType</code>
	 *
	 * @exception IllegalArgumentException
	 *                if the <code>valueType</code> is not valid or the
	 *                <code>value</code> for the given legal
	 *                <code>valueType</code> is outside the valid range
	 *
	 */

	public DataElement(int valueType, long value) {
		switch (valueType) {
		case U_INT_1:
			if (value < 0 || value > 0xff) {
				throw new IllegalArgumentException(value + " not U_INT_1");
			}
			break;
		case U_INT_2:
			if (value < 0 || value > 0xffff) {
				throw new IllegalArgumentException(value + " not U_INT_2");
			}
			break;
		case U_INT_4:
			if (value < 0 || value > 0xffffffffl) {
				throw new IllegalArgumentException(value + " not U_INT_4");
			}
			break;
		case INT_1:
			if (value < -0x80 || value > 0x7f) {
				throw new IllegalArgumentException(value + " not INT_1");
			}
			break;
		case INT_2:
			if (value < -0x8000 || value > 0x7fff) {
				throw new IllegalArgumentException(value + " not INT_2");
			}
			break;
		case INT_4:
			if (value < -0x80000000 || value > 0x7fffffff) {
				throw new IllegalArgumentException(value + " not INT_4");
			}
			break;
		case INT_8:
			// Not boundaries tests
			break;
		default:
			throw new IllegalArgumentException("type " + typeToString(valueType) + " can't be represented long");
		}

		this.value = new Long(value);
		this.valueType = valueType;
	}

	/**
	 * Creates a <code>DataElement</code> whose data type is given by
	 * <code>valueType</code> and whose value is specified by the argument
	 * <code>value</code>. The legal values for the <code>valueType</code>
	 * and the corresponding attribute values are: <TABLE>
	 * <TR>
	 * <TH>Value Type</TH>
	 * <TH>Java Type / Value Range</TH>
	 * </TR>
	 * <TR>
	 * <TD><code>URL</code></TD>
	 * <TD><code>java.lang.String</code> </TD>
	 * </TR>
	 * <TR>
	 * <TD><code>UUID</code></TD>
	 * <TD><code>javax.bluetooth.UUID</code></TD>
	 * </TR>
	 * <TR>
	 * <TD><code>STRING</code></TD>
	 * <TD><code>java.lang.String</code></TD>
	 * </TR>
	 * <TR>
	 * <TD><code>INT_16</code></TD>
	 * <TD>[-2<sup>127</sup>, 2<sup>127</sup>-1] as a byte array whose
	 * length must be 16</TD>
	 * </TR>
	 * <TR>
	 * <TD><code>U_INT_8</code></TD>
	 * <TD>[0, 2<sup>64</sup>-1] as a byte array whose length must be 8</TD>
	 * </TR>
	 * <TR>
	 * <TD><code>U_INT_16</code></TD>
	 * <TD>[0, 2<sup>128</sup>-1] as a byte array whose length must be 16</TD>
	 * </TR>
	 * </TABLE> All other pairings are illegal and would cause an
	 * <code>IllegalArgumentException</code> exception.
	 *
	 * @see #URL
	 * @see #UUID
	 * @see #STRING
	 * @see #U_INT_8
	 * @see #INT_16
	 * @see #U_INT_16
	 *
	 * @param valueType
	 *            the data type of the object that is being created; must be one
	 *            of the following: <code>URL</code>, <code>UUID</code>,
	 *            <code>STRING</code>, <code>INT_16</code>,
	 *            <code>U_INT_8</code>, or <code>U_INT_16</code>
	 *
	 * @param value
	 *            the value for the <code>DataElement</code> being created of
	 *            type <code>valueType</code>
	 *
	 * @exception IllegalArgumentException
	 *                if the <code>value</code> is not of the
	 *                <code>valueType</code> type or is not in the range
	 *                specified or is <code>null</code>
	 *
	 */

	public DataElement(int valueType, Object value) {
		if (value == null) {
			throw new IllegalArgumentException("value param is null");
		}
		switch (valueType) {
		case URL:
		case STRING:
			if (!(value instanceof String)) {
				throw new IllegalArgumentException("value param should be String");
			}
			break;
		case UUID:
			if (!(value instanceof UUID)) {
				throw new IllegalArgumentException("value param should be UUID");
			}
			break;
		case U_INT_8:
			if (!(value instanceof byte[]) || ((byte[]) value).length != 8) {
				throw new IllegalArgumentException("value param should be byte[8]");
			}
			break;
		case U_INT_16:
		case INT_16:
			if (!(value instanceof byte[]) || ((byte[]) value).length != 16) {
				throw new IllegalArgumentException("value param should be byte[16]");
			}
			break;
		default:
			throw new IllegalArgumentException("type " + typeToString(valueType) + " can't be represented by Object");
		}
		this.value = value;
		this.valueType = valueType;
	}

	/**
	 * Adds a <code>DataElement</code> to this <code>DATALT</code> or
	 * <code>DATSEQ</code> <code>DataElement</code> object. The
	 * <code>elem</code> will be added at the end of the list. The
	 * <code>elem</code> can be of any <code>DataElement</code> type, i.e.,
	 * <code>URL</code>, <code>NULL</code>, <code>BOOL</code>,
	 * <code>UUID</code>, <code>STRING</code>, <code>DATSEQ</code>,
	 * <code>DATALT</code>, and the various signed and unsigned integer
	 * types. The same object may be added twice. If the object is successfully
	 * added the size of the <code>DataElement</code> is increased by one.
	 *
	 * @param elem
	 *            the <code>DataElement</code> object to add
	 *
	 * @exception ClassCastException
	 *                if the method is invoked on a <code>DataElement</code>
	 *                whose type is not <code>DATALT</code> or
	 *                <code>DATSEQ</code>
	 *
	 * @exception NullPointerException
	 *                if <code>elem</code> is <code>null</code>
	 *
	 */

	public void addElement(DataElement elem) {
		if (elem == null) {
			throw new NullPointerException("elem param is null");
		}
		switch (valueType) {
		case DATALT:
		case DATSEQ:
			((Vector) value).addElement(elem);
			break;
		default:
			throw new ClassCastException("DataType is not DATSEQ or DATALT");
		}
	}

	/**
	 * Inserts a <code>DataElement</code> at the specified location. This
	 * method can be invoked only on a <code>DATALT</code> or
	 * <code>DATSEQ</code> <code>DataElement</code>. <code>elem</code>
	 * can be of any <code>DataElement</code> type, i.e., <code>URL</code>,
	 * <code>NULL</code>, <code>BOOL</code>, <code>UUID</code>,
	 * <code>STRING</code>, <code>DATSEQ</code>, <code>DATALT</code>,
	 * and the various signed and unsigned integers. The same object may be
	 * added twice. If the object is successfully added the size will be
	 * increased by one. Each element with an index greater than or equal to the
	 * specified index is shifted upward to have an index one greater than the
	 * value it had previously.
	 * <P>
	 * The <code>index</code> must be greater than or equal to 0 and less than
	 * or equal to the current size. Therefore, <code>DATALT</code> and
	 * <code>DATSEQ</code> are zero-based objects.
	 *
	 * @param elem
	 *            the <code>DataElement</code> object to add
	 *
	 * @param index
	 *            the location at which to add the <code>DataElement</code>
	 *
	 * @throws ClassCastException
	 *             if the method is invoked on an instance of
	 *             <code>DataElement</code> whose type is not
	 *             <code>DATALT</code> or <code>DATSEQ</code>
	 *
	 * @throws IndexOutOfBoundsException
	 *             if <code>index</code> is negative or greater than the size
	 *             of the <code>DATALT</code> or <code>DATSEQ</code>
	 *
	 * @throws NullPointerException
	 *             if <code>elem</code> is <code>null</code>
	 *
	 */

	public void insertElementAt(DataElement elem, int index) {
		if (elem == null) {
			throw new NullPointerException("elem param is null");
		}
		switch (valueType) {
		case DATALT:
		case DATSEQ:
			((Vector) value).insertElementAt(elem, index);
			break;
		default:
			throw new ClassCastException("DataType is not DATSEQ or DATALT");
		}
	}

	/**
	 * Returns the number of <code>DataElements</code> that are present in
	 * this <code>DATALT</code> or <code>DATSEQ</code> object. It is
	 * possible that the number of elements is equal to zero.
	 *
	 * @return the number of elements in this <code>DATALT</code> or
	 *         <code>DATSEQ</code>
	 *
	 * @throws ClassCastException
	 *             if this object is not of type <code>DATALT</code> or
	 *             <code>DATSEQ</code>
	 */

	public int getSize() {
		switch (valueType) {
		case DATALT:
		case DATSEQ:
			return ((Vector) value).size();
		default:
			throw new ClassCastException("DataType is not DATSEQ or DATALT");
		}
	}

	/**
	 * Removes the first occurrence of the <code>DataElement</code> from this
	 * object. <code>elem</code> may be of any type, i.e., <code>URL</code>,
	 * <code>NULL</code>, <code>BOOL</code>, <code>UUID</code>,
	 * <code>STRING</code>, <code>DATSEQ</code>, <code>DATALT</code>,
	 * or the variously sized signed and unsigned integers. Only the first
	 * object in the list that is equal to <code>elem</code> will be removed.
	 * Other objects, if present, are not removed. Since this class doesn't
	 * override the <code>equals()</code> method of the <code>Object</code>
	 * class, the remove method compares only the references of objects. If
	 * <code>elem</code> is successfully removed the size of this
	 * <code>DataElement</code> is decreased by one. Each
	 * <code>DataElement</code> in the <code>DATALT</code> or
	 * <code>DATSEQ</code> with an index greater than the index of
	 * <code>elem</code> is shifted downward to have an index one smaller than
	 * the value it had previously.
	 *
	 * @param elem
	 *            the <code>DataElement</code> to be removed
	 *
	 * @return <code>true</code> if the input value was found and removed;
	 *         else <code>false</code>
	 *
	 * @throws ClassCastException
	 *             if this object is not of type <code>DATALT</code> or
	 *             <code>DATSEQ</code>
	 *
	 * @throws NullPointerException
	 *             if <code>elem</code> is <code>null</code>
	 */

	public boolean removeElement(DataElement elem) {
		if (elem == null) {
			throw new NullPointerException("elem param is null");
		}
		switch (valueType) {
		case DATALT:
		case DATSEQ:
			return ((Vector) value).removeElement(elem);
		default:
			throw new ClassCastException("DataType is not DATSEQ or DATALT");
		}
	}

	/**
	 * Returns the data type of the object this <code>DataElement</code>
	 * represents.
	 *
	 * @return the data type of this <code>DataElement<code> object; the legal
	 * return values are:
	 *        <code>URL</code>,
	 *        <code>NULL</code>,
	 *        <code>BOOL</code>,
	 *        <code>UUID</code>,
	 *        <code>STRING</code>,
	 *        <code>DATSEQ</code>,
	 *        <code>DATALT</code>,
	 *        <code>U_INT_1</code>,
	 *        <code>U_INT_2</code>,
	 *        <code>U_INT_4</code>,
	 *        <code>U_INT_8</code>,
	 *        <code>U_INT_16</code>,
	 *        <code>INT_1</code>,
	 *        <code>INT_2</code>,
	 *        <code>INT_4</code>,
	 *        <code>INT_8</code>, or
	 *        <code>INT_16</code>
	 *
	 */

	public int getDataType() {
		return valueType;
	}

	/**
	 * Returns the value of the <code>DataElement</code> if it can be
	 * represented as a <code>long</code>. The data type of the object must
	 * be <code>U_INT_1</code>, <code>U_INT_2</code>, <code>U_INT_4</code>,
	 * <code>INT_1</code>, <code>INT_2</code>, <code>INT_4</code>, or
	 * <code>INT_8</code>.
	 *
	 *
	 * @return the value of the <code>DataElement</code> as a
	 *         <code>long</code>
	 *
	 * @throws ClassCastException
	 *             if the data type of the object is not <code>U_INT_1</code>,
	 *             <code>U_INT_2</code>, <code>U_INT_4</code>,
	 *             <code>INT_1</code>, <code>INT_2</code>,
	 *             <code>INT_4</code>, or <code>INT_8</code>
	 */

	public long getLong() {
		switch (valueType) {
		case U_INT_1:
		case U_INT_2:
		case U_INT_4:
		case INT_1:
		case INT_2:
		case INT_4:
		case INT_8:
			return ((Long) value).longValue();
		default:
			throw new ClassCastException("DataType is not INT");
		}
	}

	/**
	 * Returns the value of the <code>DataElement</code> if it is represented
	 * as a <code>boolean</code>.
	 *
	 *
	 * @return the <code>boolean</code> value of this <code>DataElement</code>
	 *         object
	 *
	 * @throws ClassCastException
	 *             if the data type of this object is not of type
	 *             <code>BOOL</code>
	 */

	public boolean getBoolean() {
		if (valueType == BOOL) {
			return ((Boolean) value).booleanValue();
		} else {
			throw new ClassCastException("DataType is not BOOL");
		}
	}

	/**
	 * Returns the value of this <code>DataElement</code> as an
	 * <code>Object</code>. This method returns the appropriate Java object
	 * for the following data types: <code>URL</code>, <code>UUID</code>,
	 * <code>STRING</code>, <code>DATSEQ</code>, <code>DATALT</code>,
	 * <code>U_INT_8</code>, <code>U_INT_16</code>, and
	 * <code>INT_16</code>. Modifying the returned <code>Object</code> will
	 * not change this <code>DataElement</code>.
	 *
	 * The following are the legal pairs of data type and Java object type being
	 * returned. <TABLE>
	 * <TR>
	 * <TH><code>DataElement</code> Data Type</code></TH>
	 * <TH>Java Data Type</TH>
	 * </TR>
	 * <TR>
	 * <TD><code>URL</code></TD>
	 * <TD><code>java.lang.String</code> </TD>
	 * </TR>
	 * <TR>
	 * <TD><code>UUID</code></TD>
	 * <TD><code>javax.bluetooth.UUID</code></TD>
	 * </TR>
	 * <TR>
	 * <TD><code>STRING</code></TD>
	 * <TD><code>java.lang.String </code></TD>
	 * </TR>
	 * <TR>
	 * <TD><code>DATSEQ</code></TD>
	 * <TD><code>java.util.Enumeration</code></TD>
	 * </TR>
	 * <TR>
	 * <TD><code>DATALT</code></TD>
	 * <TD><code>java.util.Enumeration</code></TD>
	 * </TR>
	 * <TR>
	 * <TD><code>U_INT_8</code></TD>
	 * <TD>byte[] of length 8</TD>
	 * </TR>
	 * <TR>
	 * <TD><code>U_INT_16</code></TD>
	 * <TD>byte[] of length 16</TD>
	 * </TR>
	 * <TR>
	 * <TD><code>INT_16</code></TD>
	 * <TD>byte[] of length 16</TD>
	 * </TR>
	 * </TABLE>
	 *
	 * @return the value of this object
	 *
	 * @throws ClassCastException
	 *             if the object is not a <code>URL</code>, <code>UUID</code>,
	 *             <code>STRING</code>, <code>DATSEQ</code>, <code>DATALT</code>,
	 *             <code>U_INT_8</code>, <code>U_INT_16</code>, or <code>INT_16</code>
	 *
	 */

	public Object getValue() {
		switch (valueType) {
		case URL:
		case STRING:
		case UUID:
			return value;
		case U_INT_8:
		case U_INT_16:
		case INT_16:
			// Modifying the returned Object will not change this DataElemen
			return Utils.clone((byte[]) value);
		case DATSEQ:
		case DATALT:
			return ((Vector) value).elements();
		default:
			throw new ClassCastException("DataType is simple java type");
		}
	}

	private static String typeToString(int type) {
		switch (type) {
		case DataElement.NULL:
			return "NULL";
		case DataElement.U_INT_1:
			return "U_INT_1";
		case DataElement.U_INT_2:
			return "U_INT_2";
		case DataElement.U_INT_4:
			return "U_INT_4";
		case DataElement.U_INT_8:
            return "U_INT_8";
		case DataElement.U_INT_16:
            return "U_INT_16";
		case DataElement.INT_1:
			return "INT_1";
		case DataElement.INT_2:
			return "INT_2";
		case DataElement.INT_4:
			return "INT_4";
		case DataElement.INT_8:
			return "INT_8";
		case DataElement.INT_16:
			return "INT_16";
		case DataElement.URL:
			return "URL";
		case DataElement.STRING:
			return "STRING";
		case DataElement.UUID:
			return "UUID";
		case DataElement.DATSEQ:
			return "DATSEQ";
		case DataElement.BOOL:
			return "BOOL";
		case DataElement.DATALT:
			return "DATALT";
		default:
			return "Unknown" + type;
		}
	}

	/**
	 * Non JSR-82 function.
	 *
	 * @deprecated Use ((Object)dataElement).toString() if you want your
	 *             application to run in MDIP profile
	 */
	public String toString() {
		switch (valueType) {
		case U_INT_1:
		case U_INT_2:
		case U_INT_4:
		case INT_1:
		case INT_2:
		case INT_4:
		case INT_8:
			return typeToString(valueType) + " 0x" + Utils.toHexString(((Long) value).longValue());
		case BOOL:
		case URL:
		case STRING:
		case UUID:
			return typeToString(valueType) + " " + value.toString();
		case U_INT_8:
		case U_INT_16:
		case INT_16: {
			byte[] b = (byte[]) value;

			StringBuffer buf = new StringBuffer();
			buf.append(typeToString(valueType)).append(" ");

			for (int i = 0; i < b.length; i++) {
				buf.append(Integer.toHexString(b[i] >> 4 & 0xf));
				buf.append(Integer.toHexString(b[i] & 0xf));
			}

			return buf.toString();
		}
		case DATSEQ: {
			StringBuffer buf = new StringBuffer("DATSEQ {\n");

			for (Enumeration e = ((Vector) value).elements(); e.hasMoreElements();) {
				buf.append(e.nextElement());
				buf.append("\n");
			}

			buf.append("}");

			return buf.toString();
		}
		case DATALT: {
			StringBuffer buf = new StringBuffer("DATALT {\n");

			for (Enumeration e = ((Vector) value).elements(); e.hasMoreElements();) {
				buf.append(e.nextElement());
				buf.append("\n");
			}

			buf.append("}");

			return buf.toString();
		}
		default:
			return "Unknown" + valueType;
		}
	}
}
